#include "link_node.h"
#include "framebuf.h"

#define CONTAINER_OF(type, mbr, mbr_addr) \
    (type*)(((uint64_t)mbr_addr) - ((uint64_t) (uintptr_t)(&((type*)0)->mbr)))
    
using namespace usnet;

LinkNode::LinkNode(LinkNode&& link)
{
    // bool expect { true };
    // while (accessable_.compare_exchange_weak(expect, false) == false);
    if (((uint64_t) link.next_) != ((uint64_t) &link) &&
        ((uint64_t) link.prev_) != ((uint64_t) &link)) {
        auto prev = link.prev_;
        auto next = link.next_;
        prev->next_ = this;
        this->next_ = next;
        next->prev_ = this;
        this->prev_ = prev;
        link.next_ = &link;
        link.prev_ = &link;
    }
    // accessable_.store(expect);
}

LinkNode& LinkNode::operator=(LinkNode&& link)
{
    // bool expect { true };
    // while (accessable_.compare_exchange_weak(expect, false) == false);
    if (((uint64_t) link.next_) != ((uint64_t) &link) &&
        ((uint64_t) link.prev_) != ((uint64_t) &link)) {
        auto prev = link.prev_;
        auto next = link.next_;
        prev->next_ = this;
        this->next_ = next;
        next->prev_ = this;
        this->prev_ = prev;
        link.next_ = &link;
        link.prev_ = &link;
    }
    // accessable_.store(expect);
    return *this;
}

FrameBuf* LinkNode::GetHead()
{
    // bool expect { true };
    // while (accessable_.compare_exchange_weak(expect, false) == false);
    if (((uint64_t) next_) == ((uint64_t) this) &&
        ((uint64_t) prev_) == ((uint64_t) this)) {
        // accessable_.store(expect);
        return nullptr;
    }
    FrameBuf* fb = CONTAINER_OF(FrameBuf, link_, next_);
    // accessable_.store(expect);
    return fb;
}

FrameBuf* LinkNode::GetTail()
{
    // bool expect { true };
    // while (accessable_.compare_exchange_weak(expect, false) == false);
    if (((uint64_t) next_) == ((uint64_t) this) &&
        ((uint64_t) prev_) == ((uint64_t) this)) {
        // accessable_.store(expect);
        return nullptr;
    }
    FrameBuf* fb = CONTAINER_OF(FrameBuf, link_, prev_);
    // accessable_.store(expect);
    return fb;
}

void LinkNode::RemoveHead()
{
    // bool expect { true };
    // while (accessable_.compare_exchange_weak(expect, false) == false);
    if (((uint64_t) next_) == ((uint64_t) this) &&
        ((uint64_t) prev_) == ((uint64_t) this)) {
        // accessable_.store(expect);
        return;
    }
    auto link = next_->next_;
    this->next_ = link;
    link->prev_ = this;
    // accessable_.store(expect);
}

void LinkNode::RemoveTail()
{
    // bool expect { true };
    // while (accessable_.compare_exchange_weak(expect, false) == false);
    if (((uint64_t) next_) == ((uint64_t) this) &&
        ((uint64_t) prev_) == ((uint64_t) this)) {
        // accessable_.store(expect);
        return;
    }
    auto link = prev_->prev_;
    this->prev_ = link;
    link->next_ = this;
    // accessable_.store(expect);
}

void LinkNode::RemoveNode(FrameBuf* fb)
{
    auto prev = fb->link_.prev_;
    auto next = fb->link_.next_;
    prev->next_ = next;
    next->prev_ = prev;
}

void LinkNode::HeadInsert(FrameBuf* fb)
{
    // bool expect { true };
    // while (accessable_.compare_exchange_weak(expect, false) == false);
    auto target_link = &fb->link_;
    auto link = next_;
    this->next_ = target_link;
    target_link->next_ = link;
    link->prev_ = target_link;
    target_link->prev_ = this;
    // accessable_.store(expect);
}

void LinkNode::TailInsert(FrameBuf* fb)
{
    // bool expect { true };
    // while (accessable_.compare_exchange_weak(expect, false) == false);
    auto target_link = &fb->link_;
    auto link = prev_;
    this->prev_ = target_link;
    target_link->prev_ = link;
    link->next_ = target_link;
    target_link->next_ = this;
    // accessable_.store(expect);
}